{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/nceder/qpb4e/blob/main/code/Chapter%2015/Chapter_15.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 15 Classes and object-oriented programming"
      ],
      "metadata": {
        "id": "2wG8NWI7F9DI"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 15.1.1 Using a class instance as a structure or record"
      ],
      "metadata": {
        "id": "HXEESOpRGGSH"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "E60NgT-in0HZ",
        "outputId": "db43bea0-7873-4f72-9167-2dab047fd67b",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "class Circle:\n",
        "    pass\n",
        "\n",
        "my_circle = Circle()\n",
        "my_circle.radius = 5\n",
        "print(2 * 3.14 * my_circle.radius)"
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "31.400000000000002\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9_szHCxQn0Hb",
        "outputId": "cf081587-65e0-4446-931d-a99099f6646d",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "class Circle:\n",
        "    def __init__(self):          #A\n",
        "        self.radius = 1\n",
        "my_circle = Circle()                  #B\n",
        "print(2 * 3.14 * my_circle.radius)    #C\n",
        "\n",
        "my_circle.radius = 5                 #D\n",
        "print(2 * 3.14 * my_circle.radius)   #E\n"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "6.28\n",
            "31.400000000000002\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 15.2 Instance variables"
      ],
      "metadata": {
        "id": "wU2C0rmoGffd"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "n0t9yRUhn0Hc"
      },
      "source": [
        "class Circle:\n",
        "    def __init__(self):\n",
        "        self.radius = 1"
      ],
      "execution_count": 3,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Try This: Instance Variables\n",
        "\n",
        "What code would you use to create a Rectangle class?"
      ],
      "metadata": {
        "id": "iAVgQtl7L-bq"
      }
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "q144pp5-MAfr"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# @title\n",
        "class Rectangle:\n",
        "    def __init__(self, height, width):\n",
        "        self.height = height\n",
        "        self.width = width"
      ],
      "metadata": {
        "cellView": "form",
        "id": "EEEzCnfTMAkT"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 15.3 Methods"
      ],
      "metadata": {
        "id": "vJx3g65QGk3O"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ApNXLNCen0Hc",
        "outputId": "fd6b1b87-1c1f-4886-abe8-e5e5b03783d1",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "class Circle:\n",
        "    def __init__(self):\n",
        "        self.radius = 1\n",
        "    def area(self):\n",
        "        return self.radius * self.radius * 3.14159\n",
        "\n",
        "c = Circle()\n",
        "c.radius = 3\n",
        "print(c.area())"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "28.27431\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "vFu3AiTNn0Hd",
        "outputId": "c3d09eb6-d2a6-47b1-e680-22ad304e92ed",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "print(Circle.area(c))"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "28.27431\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "bGDhszaLn0Hd"
      },
      "source": [
        "class Circle:\n",
        "    def __init__(self, radius):\n",
        "        self.radius = radius\n",
        "    def area(self):\n",
        "        return self.radius * self.radius * 3.14159"
      ],
      "execution_count": 6,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Try This: Instance variables and Methods\n",
        "\n",
        "Update the code for a `Rectangle` class so that you can set the dimensions when an instance is created, just as for the `Circle` class above. Also, add an `area()` method."
      ],
      "metadata": {
        "id": "qC1e1rK6MYnP"
      }
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "RmzzidtdMW8W"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# @title\n",
        "class Rectangle:\n",
        "    def __init__(self, height, width):\n",
        "        self.height = height\n",
        "        self.width = width\n",
        "\n",
        "    def area(self):\n",
        "        return self.height * self.width"
      ],
      "metadata": {
        "cellView": "form",
        "id": "njczXfxHMXFW"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 15.4 Class variables"
      ],
      "metadata": {
        "id": "AFNHOZPoG72t"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rk2qUS_in0Hd"
      },
      "source": [
        "class Circle:\n",
        "    pi = 3.14159\n",
        "    def __init__(self, radius):\n",
        "        self.radius = radius\n",
        "    def area(self):\n",
        "        return self.radius * self.radius * Circle.pi"
      ],
      "execution_count": 7,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "2Ehp-92in0He",
        "outputId": "5773e0d0-cede-48ed-c0d1-7b5344eb686a",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "Circle.pi"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "3.14159"
            ]
          },
          "metadata": {},
          "execution_count": 8
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "R_VL4BL7n0He",
        "outputId": "fe52b7f6-c749-4f38-b604-21f873af47c0",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "Circle.pi = 4\n",
        "Circle.pi"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "4"
            ]
          },
          "metadata": {},
          "execution_count": 9
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "g-ufUUIen0He",
        "outputId": "100fb911-f323-4a48-e1a7-cb9575c1557e",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "Circle.pi = 3.14159\n",
        "Circle.pi"
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "3.14159"
            ]
          },
          "metadata": {},
          "execution_count": 10
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zgahQ7a3n0Hf",
        "outputId": "1822ac94-5f7d-443e-be39-de1c09d0efec",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c = Circle(3)\n",
        "c.area()"
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "28.27431"
            ]
          },
          "metadata": {},
          "execution_count": 11
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "UdANorTfn0Hf",
        "outputId": "97431556-67be-451b-9ea7-0518fdc096fa",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "print(Circle)"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "<class '__main__.Circle'>\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "h6kzJ0dgn0Hg",
        "outputId": "110455fa-aa10-4b8d-b7a7-c9aa4d6f87cb",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "print(c.__class__)"
      ],
      "execution_count": 13,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "<class '__main__.Circle'>\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rb-b-NgNn0Hg",
        "outputId": "40dfc7f3-0326-4b16-ea01-a9e641d8a1f0",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c.__class__.pi"
      ],
      "execution_count": 14,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "3.14159"
            ]
          },
          "metadata": {},
          "execution_count": 14
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 15.4.1 An oddity with class variables"
      ],
      "metadata": {
        "id": "GmXRVJ_lHuG6"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "P45Thmb7n0Hg",
        "outputId": "9efd39ec-830a-41a6-a204-98b5fcae041f",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c = Circle(3)\n",
        "c.pi"
      ],
      "execution_count": 15,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "3.14159"
            ]
          },
          "metadata": {},
          "execution_count": 15
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "K7kYNTjTn0Hh",
        "outputId": "7539fe2b-0e0b-492b-abb3-22ca82a3b259",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c1 = Circle(1)\n",
        "c2 = Circle(2)\n",
        "c1.pi = 3.14\n",
        "c1.pi"
      ],
      "execution_count": 16,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "3.14"
            ]
          },
          "metadata": {},
          "execution_count": 16
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "NP0oXUW-n0Hh",
        "outputId": "3b05dff5-4562-4044-a213-96eae3241941",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c2.pi"
      ],
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "3.14159"
            ]
          },
          "metadata": {},
          "execution_count": 17
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "TYsLYMR0n0Hh",
        "outputId": "f9473935-9962-49c2-dfb8-41481e6eb365",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "Circle.pi"
      ],
      "execution_count": 18,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "3.14159"
            ]
          },
          "metadata": {},
          "execution_count": 18
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Listing 15.1 File circle.py"
      ],
      "metadata": {
        "id": "MgjaJ_u3IHrb"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!wget https://raw.githubusercontent.com/nceder/qpb4e/main/code/Chapter%2015/circle.py &> /dev/null  && echo Downloaded"
      ],
      "metadata": {
        "id": "CiuNzvMCJyiU",
        "outputId": "20308488-b286-465d-fad2-15e7d8d7226e",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 19,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Downloaded\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "mY6eRHkon0Hh"
      },
      "source": [
        "\"\"\"circle module: contains the Circle class.\"\"\"\n",
        "class Circle:\n",
        "    \"\"\"Circle class\"\"\"\n",
        "    all_circles = []             #A\n",
        "    pi = 3.14159\n",
        "    def __init__(self, r=1):\n",
        "        \"\"\"Create a Circle with the given radius\"\"\"\n",
        "        self.radius = r\n",
        "        self.__class__.all_circles.append(self)   #B\n",
        "    def area(self):\n",
        "        \"\"\"determine the area of the Circle\"\"\"\n",
        "        return self.__class__.pi * self.radius * self.radius\n",
        "\n",
        "    @staticmethod\n",
        "    def total_area():\n",
        "        \"\"\"Static method to total the areas of all Circles \"\"\"\n",
        "        total = 0\n",
        "        for c in Circle.all_circles:\n",
        "            total = total + c.area()\n",
        "        return total"
      ],
      "execution_count": 20,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "jKiDJY2Jn0Hi",
        "outputId": "95b4c762-0210-477c-a1e1-88ffc200f837",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "import circle\n",
        "c1 = circle.Circle(1)\n",
        "c2 = circle.Circle(2)\n",
        "circle.Circle.total_area()"
      ],
      "execution_count": 21,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "15.70795"
            ]
          },
          "metadata": {},
          "execution_count": 21
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zCwEncdfn0Hi",
        "outputId": "1f74c15c-0624-494c-d2ce-bf8bad489f73",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c2.radius = 3\n",
        "circle.Circle.total_area()"
      ],
      "execution_count": 22,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "31.415899999999997"
            ]
          },
          "metadata": {},
          "execution_count": 22
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hj1cObkkn0Hi",
        "outputId": "55f298ad-46d0-418e-ed64-ef6cbbb2c67a",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "circle.__doc__"
      ],
      "execution_count": 23,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "'circle module: contains the Circle class.'"
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 23
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Kv2u_29Mn0Hj",
        "outputId": "035566e9-9e46-45c4-8985-2338fe6b7175",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "circle.Circle.__doc__"
      ],
      "execution_count": 24,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "'Circle class'"
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 24
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "lDTIBQ3En0Hj",
        "outputId": "384890b0-0629-4cc8-8613-924295c99c5e",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "circle.Circle.area.__doc__"
      ],
      "execution_count": 25,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "'determine the area of the Circle'"
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 25
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 15.5.2 Class methods"
      ],
      "metadata": {
        "id": "x_iLz47mI31S"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!wget https://raw.githubusercontent.com/nceder/qpb4e/main/code/Chapter%2015/circle_cm.py &> /dev/null  && echo Downloaded"
      ],
      "metadata": {
        "id": "lb4SIOxZJ7vF",
        "outputId": "97fdc830-39d5-49f2-ede0-6f22ea47d02c",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 26,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Downloaded\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Listing 15.2 File circle_cm.py"
      ],
      "metadata": {
        "id": "XQxgXMoyI91K"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "gVUMS8Hsn0Hj"
      },
      "source": [
        "\"\"\"circle_cm module: contains the Circle class.\"\"\"\n",
        "class Circle:\n",
        "    \"\"\"Circle class\"\"\"\n",
        "    all_circles = []              #A\n",
        "    pi = 3.14159\n",
        "    def __init__(self, r=1):\n",
        "        \"\"\"Create a Circle with the given radius\"\"\"\n",
        "        self.radius = r\n",
        "        self.__class__.all_circles.append(self)\n",
        "    def area(self):\n",
        "        \"\"\"determine the area of the Circle\"\"\"\n",
        "        return self.__class__.pi * self.radius * self.radius\n",
        "\n",
        "    @classmethod             #A\n",
        "    def total_area(cls):              #B\n",
        "        total = 0\n",
        "        for c in cls.all_circles:          #C\n",
        "            total = total + c.area()\n",
        "        return total\n"
      ],
      "execution_count": 27,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "AnXIP9hLn0Hj",
        "outputId": "2cbdbc86-2131-4221-a2a9-32db54f52cd7",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "import circle_cm\n",
        "c1 = circle_cm.Circle(1)\n",
        "c2 = circle_cm.Circle(2)\n",
        "circle_cm.Circle.total_area()"
      ],
      "execution_count": 28,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "15.70795"
            ]
          },
          "metadata": {},
          "execution_count": 28
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "jadsSIYxn0Hk",
        "outputId": "4f20e16b-68b9-4477-c19a-cd36837c31df",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c2.radius = 3\n",
        "circle_cm.Circle.total_area()"
      ],
      "execution_count": 29,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "31.415899999999997"
            ]
          },
          "metadata": {},
          "execution_count": 29
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Try This: Class methods\n",
        "\n",
        "Write a class method similar to `total_area()` that returns the total circumference of all circles."
      ],
      "metadata": {
        "id": "1h8XWMS-MxjA"
      }
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "XYF88xSHM4ZS"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# @title\n",
        "class Circle:\n",
        "    pi = 3.14159\n",
        "    all_circles = []\n",
        "    def __init__(self, radius):\n",
        "        self.radius = radius\n",
        "        self.__class__.all_circles.append(self)\n",
        "\n",
        "    def area(self):\n",
        "        return self.radius * self.radius * Circle.pi\n",
        "\n",
        "    def circumference(self):\n",
        "        return 2 * self.radius * Circle.pi\n",
        "\n",
        "    @classmethod\n",
        "    def total_circumference(cls):\n",
        "        \"\"\"class method to total the circumference of all Circles \"\"\"\n",
        "        total = 0\n",
        "        for c in cls.all_circles:\n",
        "            total = total + c.circumference()\n",
        "        return total"
      ],
      "metadata": {
        "cellView": "form",
        "id": "TFrUs3Q7M4gl"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 15.6 Inheritance"
      ],
      "metadata": {
        "id": "2Jz9jTl3KFby"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ZzwOg-pqn0Hk"
      },
      "source": [
        "class Square:\n",
        "    def __init__(self, side=1):\n",
        "        self.side = side                     #A"
      ],
      "execution_count": 30,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fWyVbS5Sn0Hk"
      },
      "source": [
        "class Square:\n",
        "    def __init__(self, side=1, x=0, y=0):\n",
        "        self.side = side\n",
        "        self.x = x\n",
        "        self.y = y\n",
        "class Circle:\n",
        "    def __init__(self, radius=1, x=0, y=0):\n",
        "        self.radius = radius\n",
        "        self.x = x\n",
        "        self.y = y"
      ],
      "execution_count": 31,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "vr9lBzDCn0Hk"
      },
      "source": [
        "class Shape:\n",
        "    def __init__(self, x, y):\n",
        "        self.x = x\n",
        "        self.y = y\n",
        "class Square(Shape):                                #A\n",
        "    def __init__(self, side=1, x=0, y=0):\n",
        "        super().__init__(x, y)                      #B\n",
        "        self.side = side\n",
        "class Circle(Shape):                                #C\n",
        "    def __init__(self, r=1, x=0, y=0):\n",
        "        super().__init__(x, y)            #B\n",
        "        self.radius = r"
      ],
      "execution_count": 32,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "2ASXcCFTn0Hl"
      },
      "source": [
        "class Shape:\n",
        "    def __init__(self, x, y):\n",
        "        self.x = x\n",
        "        self.y = y\n",
        "    def move(self, delta_x, delta_y):\n",
        "        self.x = self.x + delta_x\n",
        "        self.y = self.y + delta_y\n",
        "class Square(Shape):\n",
        "    def __init__(self, side=1, x=0, y=0):\n",
        "        super().__init__(x, y)\n",
        "        self.side = side\n",
        "class Circle(Shape):\n",
        "    def __init__(self, r=1, x=0, y=0):\n",
        "        super().__init__(x, y)\n",
        "        self.radius = r"
      ],
      "execution_count": 33,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "7eteKFGxn0Hl",
        "outputId": "2926a587-5e42-4349-dcd9-1916e99ac332",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "c = Circle(1)\n",
        "c.move(3, 4)\n",
        "f\"c.x = {c.x}, c.y = {c.y}\""
      ],
      "execution_count": 34,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "'c.x = 3, c.y = 4'"
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 34
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Try This: Inheritance\n",
        "\n",
        "Rewrite the code for a `Rectangle` class to inherit from `Shape`. Because squares and rectangles are related, would it make sense to inherit one from the other? If so, which would be the base class, and which would inherit?\n",
        "\n",
        "How would you write the code to add an `area()` method for the `Square` class? Should the `area` method be moved into the base `Shape` class and inherited by `Circle`, `Square`, and `Rectangle`? If so, what issues would result?"
      ],
      "metadata": {
        "id": "4auYIAe6K8Xn"
      }
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "ofpyzVH3LfKc"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# @title\n",
        "class Shape:\n",
        "    def __init__(self, x, y):\n",
        "        self.x = x\n",
        "        self.y = y\n",
        "\n",
        "class Rectangle(Shape):\n",
        "    def __init__(self, x, y):\n",
        "        super().__init__(x, y)"
      ],
      "metadata": {
        "cellView": "form",
        "id": "HV_p7blCNFoy"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 15.7 Inheritance with class and instance variables"
      ],
      "metadata": {
        "id": "TFPLMli7Lf-w"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1fArG-6nn0Hm"
      },
      "source": [
        "class P:\n",
        "    z = \"Hello\"\n",
        "    def set_p(self):\n",
        "        self.x = \"Class P\"\n",
        "    def print_p(self):\n",
        "         print(self.x)\n",
        "class C(P):\n",
        "    def set_c(self):\n",
        "        self.x = \"Class C\"\n",
        "    def print_c(self):\n",
        "        print(self.x)"
      ],
      "execution_count": 35,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fDeBZA_8n0Hm",
        "outputId": "4daf5fc3-a36f-4c6c-863a-44e88656e438",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c = C()\n",
        "c.set_p()\n",
        "c.print_p()"
      ],
      "execution_count": 36,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Class P\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LRLdeOPSn0Hm",
        "outputId": "3c91accb-df54-4f3f-81b5-51c46d618cab",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c.print_c()"
      ],
      "execution_count": 37,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Class P\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "NoBet1UCn0Hm",
        "outputId": "1ff77110-a0b9-4bd6-c1cb-b3fe39707764",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c.set_c()\n",
        "c.print_c()"
      ],
      "execution_count": 38,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Class C\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3r4HHoTrn0Hn",
        "outputId": "132f70f8-3bd1-4c17-ec17-e8dd168ff1f2",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c.print_p()"
      ],
      "execution_count": 39,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Class C\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hTgYkJNrn0Hn",
        "outputId": "8c7d2905-ea4d-40fb-97d2-fcc5430ae73a",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "f\"{c.z=} {C.z=} {P.z=}\""
      ],
      "execution_count": 40,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "\"c.z='Hello' C.z='Hello' P.z='Hello'\""
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 40
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "DJgPAnlOn0Ho",
        "outputId": "b6a46505-a594-4ad8-a0fa-8173abe4ec28",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "C.z = \"Bonjour\"\n",
        "f\"{c.z=} {C.z=} {P.z=}\""
      ],
      "execution_count": 41,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "\"c.z='Bonjour' C.z='Bonjour' P.z='Hello'\""
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 41
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "OY4mRAl4n0Ho",
        "outputId": "fa410443-d884-44ef-9842-04d5afd84f17",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "c.z = \"Ciao\"\n",
        "f\"{c.z=} {C.z=} {P.z=}\""
      ],
      "execution_count": 42,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "\"c.z='Ciao' C.z='Bonjour' P.z='Hello'\""
            ],
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            }
          },
          "metadata": {},
          "execution_count": 42
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 15.8 Recap: Basics of Python classes"
      ],
      "metadata": {
        "id": "2LTbdnL0MpdQ"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "C_nfjsJnn0Hp"
      },
      "source": [
        "class Shape:\n",
        "    def __init__(self, x, y):        #A\n",
        "        self.x = x                 #B\n",
        "        self.y = y                 #B\n",
        "    def move(self, delta_x, delta_y):  #C\n",
        "        self.x = self.x + delta_x    #D\n",
        "        self.y = self.y + delta_y"
      ],
      "execution_count": 43,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "_3bpOVaHn0Hp"
      },
      "source": [
        "class Circle(Shape):                                #A\n",
        "    pi = 3.14159           #B\n",
        "    all_circles = []       #B\n",
        "    def __init__(self, r=1, x=0, y=0):                  #C\n",
        "        super().__init__(x, y)   #D\n",
        "        self.radius = r\n",
        "        self.__class__.all_circles.append(self)     #E\n",
        "    @classmethod       #F\n",
        "    def total_area(cls):\n",
        "        area = 0\n",
        "        for circle in cls.all_circles:\n",
        "            area += cls.circle_area(circle.radius)     #G\n",
        "        return area\n",
        "    @staticmethod\n",
        "    def circle_area(radius):               #H\n",
        "        return Circle.pi * radius * radius           #I"
      ],
      "execution_count": 44,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fb_oPHCWn0Hp",
        "outputId": "a04fa5f1-51f7-4478-f77f-a0ccecce916a",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c1 = Circle()\n",
        "c1.radius, c1.x, c1.y"
      ],
      "execution_count": 45,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(1, 0, 0)"
            ]
          },
          "metadata": {},
          "execution_count": 45
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1QtVCB48n0Hp",
        "outputId": "d1de9cbc-8622-4e3b-9b00-4076a58897be",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c2 = Circle(2, 1, 1)\n",
        "c2.radius, c2.x, c2.y"
      ],
      "execution_count": 46,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(2, 1, 1)"
            ]
          },
          "metadata": {},
          "execution_count": 46
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "UATYtv9Hn0Hq",
        "outputId": "1f1c0a7d-77be-404a-930c-816f83904834",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c2.move(2, 2)\n",
        "c2.radius, c2.x, c2.y"
      ],
      "execution_count": 47,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(2, 3, 3)"
            ]
          },
          "metadata": {},
          "execution_count": 47
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zwzEZss5n0Hq",
        "outputId": "af5cc1d1-68d6-4fa5-efeb-542d243bef4e",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "Circle.all_circles"
      ],
      "execution_count": 48,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[<__main__.Circle at 0x79b66039dbd0>, <__main__.Circle at 0x79b66039dd20>]"
            ]
          },
          "metadata": {},
          "execution_count": 48
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ozveyvoyn0Hq",
        "outputId": "0543e127-b71f-40e2-d534-06e10cfc7306",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "[c1, c2]"
      ],
      "execution_count": 49,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[<__main__.Circle at 0x79b66039dbd0>, <__main__.Circle at 0x79b66039dd20>]"
            ]
          },
          "metadata": {},
          "execution_count": 49
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "MfRRCeSdn0Hq",
        "outputId": "51d4a822-951e-465c-85e5-08c48de6e167",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "Circle.total_area()"
      ],
      "execution_count": 50,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "15.70795"
            ]
          },
          "metadata": {},
          "execution_count": 50
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "b0BnanpOn0Hr",
        "outputId": "e8d5a62e-a84b-4286-fa32-a7618be8467c",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c2.total_area()"
      ],
      "execution_count": 51,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "15.70795"
            ]
          },
          "metadata": {},
          "execution_count": 51
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "N_Sxpk0qn0Hr",
        "outputId": "569ac38a-a3b6-419a-87d0-fdfa7b3b1a13",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "Circle.circle_area(c1.radius)"
      ],
      "execution_count": 52,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "3.14159"
            ]
          },
          "metadata": {},
          "execution_count": 52
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1qAmN4KXn0Hr",
        "outputId": "6212357b-3fa2-48e2-a509-c8b93ac8634b",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "c1.circle_area(c1.radius)"
      ],
      "execution_count": 53,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "3.14159"
            ]
          },
          "metadata": {},
          "execution_count": 53
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 15.9 Private variables and private methods"
      ],
      "metadata": {
        "id": "cQL6Yt9HM-6J"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "UiY_S0dXn0Hr"
      },
      "source": [
        "class Mine:\n",
        "    def __init__(self):\n",
        "        self.x = 2\n",
        "        self.__y = 3                    #A\n",
        "    def print_y(self):\n",
        "        print(self.__y)"
      ],
      "execution_count": 54,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CojcMvQJn0Hs"
      },
      "source": [
        "m = Mine()"
      ],
      "execution_count": 55,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "G1WM65fln0Hs",
        "outputId": "0c042a61-db1e-44dc-99ee-ad60784e7468",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "print(m.x)"
      ],
      "execution_count": 58,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "2\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nML3xDCjn0Hs",
        "outputId": "5ad9453e-50d3-44ed-ba8d-1f5babfa2c51",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 141
        }
      },
      "source": [
        "print(m.__y)"
      ],
      "execution_count": 59,
      "outputs": [
        {
          "output_type": "error",
          "ename": "AttributeError",
          "evalue": "'Mine' object has no attribute '__y'",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-59-c09dfe1cad43>\u001b[0m in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__y\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[0;31mAttributeError\u001b[0m: 'Mine' object has no attribute '__y'"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "EKgxxWsTn0Ht",
        "outputId": "15d7774d-f5a5-4e85-8936-5fc2afaf94b9",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "m.print_y()"
      ],
      "execution_count": 60,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "3\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "DZNDioOUn0Ht",
        "outputId": "55920110-7e00-48b7-ab8b-d1c3a6ee8fb7",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "dir(m)"
      ],
      "execution_count": 61,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "['_Mine__y',\n",
              " '__class__',\n",
              " '__delattr__',\n",
              " '__dict__',\n",
              " '__dir__',\n",
              " '__doc__',\n",
              " '__eq__',\n",
              " '__format__',\n",
              " '__ge__',\n",
              " '__getattribute__',\n",
              " '__gt__',\n",
              " '__hash__',\n",
              " '__init__',\n",
              " '__init_subclass__',\n",
              " '__le__',\n",
              " '__lt__',\n",
              " '__module__',\n",
              " '__ne__',\n",
              " '__new__',\n",
              " '__reduce__',\n",
              " '__reduce_ex__',\n",
              " '__repr__',\n",
              " '__setattr__',\n",
              " '__sizeof__',\n",
              " '__str__',\n",
              " '__subclasshook__',\n",
              " '__weakref__',\n",
              " 'print_y',\n",
              " 'x']"
            ]
          },
          "metadata": {},
          "execution_count": 61
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "###Try This: Private instance variables\n",
        "\n",
        "Modify the Rectangle class's code to make the dimension variables private. What restriction will this modification impose on using the class?\n"
      ],
      "metadata": {
        "id": "r5E3NBFANfGk"
      }
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "BBchg9QuNmhB"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# @title\n",
        "class Rectangle():\n",
        "    def __init__(self, x, y):\n",
        "        self.__x = x\n",
        "        self.__y = y"
      ],
      "metadata": {
        "cellView": "form",
        "id": "60a4OQB0Ny6i"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 15.10 Using @property for more flexible instance variables"
      ],
      "metadata": {
        "id": "-_iwJEmiNoO6"
      }
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "JjagDXIqn0Ht"
      },
      "source": [
        "class Temperature:\n",
        "    def __init__(self):\n",
        "        self._temp_fahr = 0\n",
        "    @property\n",
        "    def temp(self):\n",
        "        return (self._temp_fahr - 32) * 5 / 9"
      ],
      "execution_count": 62,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "BcXCT46Vn0Ht"
      },
      "source": [
        "class Temperature:\n",
        "    def __init__(self):\n",
        "        self._temp_fahr = 0\n",
        "    @property\n",
        "    def temp(self):\n",
        "        return (self._temp_fahr - 32) * 5 / 9\n",
        "    @temp.setter\n",
        "    def temp(self, new_temp):\n",
        "        self._temp_fahr = new_temp * 9 / 5 + 32"
      ],
      "execution_count": 63,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "BlLxnjYSn0Hu",
        "outputId": "4a039bdd-3ac7-4a0b-b3d1-e25dac306270",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "t = Temperature()\n",
        "t._temp_fahr"
      ],
      "execution_count": 64,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0"
            ]
          },
          "metadata": {},
          "execution_count": 64
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "egKzMVtSn0Hu",
        "outputId": "5aae5171-cbc2-4c3d-eee3-6acbaee4a8c1",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "t.temp"
      ],
      "execution_count": 65,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "-17.77777777777778"
            ]
          },
          "metadata": {},
          "execution_count": 65
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "wBv3L-yVn0Hu",
        "outputId": "efbbfd2d-0b99-48e3-f226-af7d5b71dfbb",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "t.temp = 34      #A\n",
        "t._temp_fahr"
      ],
      "execution_count": 66,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "93.2"
            ]
          },
          "metadata": {},
          "execution_count": 66
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Uv4MN8DRn0Hu",
        "outputId": "10466801-b564-47ad-d4ba-10b4e06f3ae5",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "t.temp     #B"
      ],
      "execution_count": 67,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "34.0"
            ]
          },
          "metadata": {},
          "execution_count": 67
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Try This: Properties\n",
        "\n",
        "Update the dimensions of the Rectangle class to be properties with getters and setters that don't allow negative sizes."
      ],
      "metadata": {
        "id": "OYaOmDGbOJqr"
      }
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "GMBYuwvYN6YM"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# @title\n",
        "class Rectangle():\n",
        "    def __init__(self, x, y):\n",
        "        self.__x = x\n",
        "        self.__y = y\n",
        "\n",
        "    @property\n",
        "    def x(self):\n",
        "        return self.__x\n",
        "\n",
        "    @x.setter\n",
        "    def x(self, new_x):\n",
        "        if new_x >= 0:\n",
        "            self.__x = new_x\n",
        "\n",
        "    @property\n",
        "    def y(self):\n",
        "        return self.__y\n",
        "\n",
        "    @y.setter\n",
        "    def y(self, new_y):\n",
        "        if new_y >= 0:\n",
        "            self.__y = new_y\n",
        "\n",
        "# test\n",
        "my_rect = Rectangle(1,2)\n",
        "print(my_rect.x, my_rect.y)\n",
        "my_rect.x = 4\n",
        "my_rect.y = 5\n",
        "print(my_rect.x, my_rect.y)"
      ],
      "metadata": {
        "cellView": "form",
        "id": "wRFLbWLON6hP"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "\n",
        "# 15.11 Scoping rules and namespaces for class instances"
      ],
      "metadata": {
        "id": "pdCoNvnCONNX"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Listing 15.3 File cs.py"
      ],
      "metadata": {
        "id": "2KkEjNTYOYHD"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!wget https://raw.githubusercontent.com/nceder/qpb4e/main/code/Chapter%2015/cs.py &> /dev/null  && echo Downloaded"
      ],
      "metadata": {
        "id": "97fhAon5O42e",
        "outputId": "345622bc-a867-43aa-e2ae-dc0e67e18ff8",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 68,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Downloaded\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "cAuNqvj5n0Hv"
      },
      "source": [
        "\"\"\"cs module: class scope demonstration module.\"\"\"\n",
        "mod_var =\"module variable: mod_var\"\n",
        "def mod_func():\n",
        "    return (\"module level function: mod_func()\")\n",
        "class SuperClass:\n",
        "    super_class_var = \"superclass class variable: self.super_class_var\"\n",
        "    __priv_super_class_var = \"private superclass class variable: no access\"\n",
        "    def __init__(self):\n",
        "        self.super_instance_var = \"superclass instance variable: self.super_instance_var \"\n",
        "        self.__psiv = \"private superclass instance variable: no access\"\n",
        "    def super_class_method(self):\n",
        "        return \"superclass method: self.super_class_method()\"\n",
        "    def superclass_priv_method(self):\n",
        "        return \"superclass private method: no access\"\n",
        "class Class_(SuperClass):\n",
        "    class_var = \"class variable: self.class_var or Class_.class_var (for assignment)\"\n",
        "    __priv_class_var = \"class private variable: self.__priv_class_var or Class_.__priv_class_var \"\n",
        "    def __init__(self):\n",
        "        SuperClass.__init__(self)\n",
        "        self.__priv_instance_var = \"private instance variable: self.__priv_instance_var\"\n",
        "    def method_2(self):\n",
        "        return \"method: self.method_2()\"\n",
        "    def __priv_method(self):\n",
        "        return \"private method: self.__priv_method()\"\n",
        "    def method_1(self, param=\"parameter: param\"):\n",
        "        local_var = \"local variable: local_var\"\n",
        "        self.instance_var = \"instance variable: self.instance_var\"\n",
        "        print(\"Local\")\n",
        "        print(\"Access local, global and built-in namespaces directly\")\n",
        "        print(\"local namespace:\", list(locals().keys()))\n",
        "        print(param)                                               #A\n",
        "\n",
        "        print(local_var)\n",
        "        print()                                       #B\n",
        "        print(\"global namespace:\", list(globals().keys()))\n",
        "        print(mod_var)                         #C\n",
        "\n",
        "        print(mod_func())\n",
        "        print()             #D\n",
        "        print(\"Access instance, class, and superclass namespaces through 'self'\")\n",
        "        print(\"Instance namespace:\", self.__dict__)\n",
        "\n",
        "        print(self.instance_var)                                       #E\n",
        "\n",
        "        print(self.__priv_instance_var)                    #F\n",
        "\n",
        "        print(self.super_instance_var)                                         #G\n",
        "        print(\"\\nClass_ namespace:\", Class_.__dict__)\n",
        "        print(self.class_var)                                          #H\n",
        "\n",
        "        print(self.method_2())                       #I\n",
        "\n",
        "        print(self.__priv_class_var)                                   #J\n",
        "\n",
        "        print(self.__priv_method())                            #K\n",
        "        print(\"\\nSuperclass namespace:\", SuperClass.__dict__)\n",
        "        print(self.super_class_method())                        #L\n",
        "\n",
        "        print(self.super_class_var)                #M\n"
      ],
      "execution_count": 69,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "bbrJK4P1n0Hv",
        "outputId": "633db698-02f9-4a7c-cc39-bd6d5ef4c934",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "source": [
        "#import cs\n",
        "#c = cs.Class_()\n",
        "#c.method_1()\n",
        "\n",
        "c = Class_()\n",
        "c.method_1()"
      ],
      "execution_count": 70,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Local\n",
            "Access local, global and built-in namespaces directly\n",
            "local namespace: ['self', 'param', 'local_var']\n",
            "parameter: param\n",
            "local variable: local_var\n",
            "\n",
            "global namespace: ['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__builtin__', '__builtins__', '_ih', '_oh', '_dh', 'In', 'Out', 'get_ipython', 'exit', 'quit', '_', '__', '___', '_i', '_ii', '_iii', '_i1', 'Circle', 'my_circle', '_i2', '_i3', '_i4', 'c', '_i5', '_i6', '_i7', '_i8', '_8', '_i9', '_9', '_i10', '_10', '_i11', '_11', '_i12', '_i13', '_i14', '_14', '_i15', '_15', '_i16', 'c1', 'c2', '_16', '_i17', '_17', '_i18', '_18', '_i19', '_exit_code', '_i20', '_i21', 'circle', '_21', '_i22', '_22', '_i23', '_23', '_i24', '_24', '_i25', '_25', '_i26', '_i27', '_i28', 'circle_cm', '_28', '_i29', '_29', '_i30', 'Square', '_i31', '_i32', 'Shape', '_i33', '_i34', '_34', '_i35', 'P', 'C', '_i36', '_i37', '_i38', '_i39', '_i40', '_40', '_i41', '_41', '_i42', '_42', '_i43', '_i44', '_i45', '_45', '_i46', '_46', '_i47', '_47', '_i48', '_48', '_i49', '_49', '_i50', '_50', '_i51', '_51', '_i52', '_52', '_i53', '_53', '_i54', 'Mine', '_i55', 'm', '_i56', '_i57', '_i58', '_i59', '_i60', '_i61', '_61', '_i62', 'Temperature', '_i63', '_i64', 't', '_64', '_i65', '_65', '_i66', '_66', '_i67', '_67', '_i68', '_i69', 'mod_var', 'mod_func', 'SuperClass', 'Class_', '_i70']\n",
            "module variable: mod_var\n",
            "module level function: mod_func()\n",
            "\n",
            "Access instance, class, and superclass namespaces through 'self'\n",
            "Instance namespace: {'super_instance_var': 'superclass instance variable: self.super_instance_var ', '_SuperClass__psiv': 'private superclass instance variable: no access', '_Class___priv_instance_var': 'private instance variable: self.__priv_instance_var', 'instance_var': 'instance variable: self.instance_var'}\n",
            "instance variable: self.instance_var\n",
            "private instance variable: self.__priv_instance_var\n",
            "superclass instance variable: self.super_instance_var \n",
            "\n",
            "Class_ namespace: {'__module__': '__main__', 'class_var': 'class variable: self.class_var or Class_.class_var (for assignment)', '_Class___priv_class_var': 'class private variable: self.__priv_class_var or Class_.__priv_class_var ', '__init__': <function Class_.__init__ at 0x79b6603ad5a0>, 'method_2': <function Class_.method_2 at 0x79b6603ad630>, '_Class___priv_method': <function Class_.__priv_method at 0x79b6603ad6c0>, 'method_1': <function Class_.method_1 at 0x79b6603ad750>, '__doc__': None}\n",
            "class variable: self.class_var or Class_.class_var (for assignment)\n",
            "method: self.method_2()\n",
            "class private variable: self.__priv_class_var or Class_.__priv_class_var \n",
            "private method: self.__priv_method()\n",
            "\n",
            "Superclass namespace: {'__module__': '__main__', 'super_class_var': 'superclass class variable: self.super_class_var', '_SuperClass__priv_super_class_var': 'private superclass class variable: no access', '__init__': <function SuperClass.__init__ at 0x79b6603ad120>, 'super_class_method': <function SuperClass.super_class_method at 0x79b6603ad090>, 'superclass_priv_method': <function SuperClass.superclass_priv_method at 0x79b6603ad240>, '__dict__': <attribute '__dict__' of 'SuperClass' objects>, '__weakref__': <attribute '__weakref__' of 'SuperClass' objects>, '__doc__': None}\n",
            "superclass method: self.super_class_method()\n",
            "superclass class variable: self.super_class_var\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 15.14 Lab 15: HTML classes\n",
        "\n",
        "In this lab, you create classes to represent an HTML document. To keep things simple, assume that each element can contain only text and one subelement. So the `<html>` element contains only a `<body>` element, and the `<body>` element contains (optional) text and a `<p>` element that contains only text.\n",
        "\n",
        "The key feature to implement is the `__str__()` method, which in turn calls its subelement's `__str__()` method, so that the entire document is returned when the `str()` function is called on an `<html>` element. You can assume that any text comes before the subelement.\n",
        "\n",
        "Here's example output from using the classes:\n",
        "```python\n",
        "para = p(text=\"this is some body text\")\n",
        "doc_body = body(text=\"This is the body\", subelement=para)\n",
        "doc = html(subelement=doc_body)\n",
        "print(doc)\n",
        "```\n",
        "```html\n",
        "<html>\n",
        "<body>\n",
        "This is the body\n",
        "<p>\n",
        "this is some body text\n",
        "</p>\n",
        "</body>\n",
        "</html>\n",
        "```"
      ],
      "metadata": {
        "id": "pPfdQQ7LPsen"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Author's solution"
      ],
      "metadata": {
        "id": "C-GMzdXCOPu1"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "class element:\n",
        "    def __init__(self, text=None, subelement=None):\n",
        "        self.subelement = subelement\n",
        "        self.text = text\n",
        "\n",
        "    def __str__(self):\n",
        "        value = f\"<{self.__class__.__name__}>\\n\"\n",
        "        if self.text:\n",
        "            value += f\"{self.text}\\n\"\n",
        "        if self.subelement:\n",
        "            value += str(self.subelement)\n",
        "        value += f\"</{self.__class__.__name__}>\\n\"\n",
        "        return value\n",
        "\n",
        "class html(element):\n",
        "    pass\n",
        "\n",
        "class body(element):\n",
        "    pass\n",
        "\n",
        "class p(element):\n",
        "    pass\n",
        "\n",
        "#test\n",
        "para = p(text=\"this is some body text\")\n",
        "doc_body = body(text=\"This is the body\", subelement=para)\n",
        "doc = html(subelement=doc_body)\n",
        "print(doc)"
      ],
      "metadata": {
        "id": "W1YonYoqPxzi",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "de552b04-c276-49cd-b6d7-9c5f3a61907b"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "<html>\n",
            "<body>\n",
            "This is the body\n",
            "<p>\n",
            "this is some body text\n",
            "</p>\n",
            "</body>\n",
            "</html>\n",
            "\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Copilot solution"
      ],
      "metadata": {
        "id": "h-LGXQcZQ970"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "class Element:\n",
        "    tag = \"\"\n",
        "\n",
        "    def __init__(self, text=\"\", subelement=None):\n",
        "        self.text = text\n",
        "        self.subelement = subelement\n",
        "\n",
        "    def __str__(self):\n",
        "        result = f\"<{self.tag}>\\n\"\n",
        "        if self.text:\n",
        "            result += self.text + \"\\n\"\n",
        "        if self.subelement:\n",
        "            result += str(self.subelement)\n",
        "        result += f\"</{self.tag}>\\n\"\n",
        "        return result\n",
        "\n",
        "class Html(Element):\n",
        "    tag = \"html\"\n",
        "\n",
        "class Body(Element):\n",
        "    tag = \"body\"\n",
        "\n",
        "class P(Element):\n",
        "    tag = \"p\"\n",
        "\n",
        "# Usage:\n",
        "para = P(text=\"this is some body text\")\n",
        "doc_body = Body(text=\"This is the body\", subelement=para)\n",
        "doc = Html(subelement=doc_body)\n",
        "print(doc)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "YRzlaYGQOXPs",
        "outputId": "fff1fcfd-b5b5-408c-f2b5-7ec8fceed6db"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "<html>\n",
            "<body>\n",
            "This is the body\n",
            "<p>\n",
            "this is some body text\n",
            "</p>\n",
            "</body>\n",
            "</html>\n",
            "\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "### Colaboratory solution\n",
        "\n",
        "(generated when immediately below problem statement)"
      ],
      "metadata": {
        "id": "nx8LgB5fdI4u"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# prompt: Generate the code described in the cell above.\n",
        "\n",
        "class html:\n",
        "    def __init__(self, subelement):\n",
        "        self.subelement = subelement\n",
        "    def __str__(self):\n",
        "        return f'<html>\\n{str(self.subelement)}\\n</html>'\n",
        "\n",
        "class body:\n",
        "    def __init__(self, text, subelement=None):\n",
        "        self.text = text\n",
        "        self.subelement = subelement\n",
        "    def __str__(self):\n",
        "        sub = ''\n",
        "        if self.subelement:\n",
        "            sub = f'\\n{str(self.subelement)}'\n",
        "        return f'<body>\\n{self.text}{sub}\\n</body>'\n",
        "\n",
        "class p:\n",
        "    def __init__(self, text):\n",
        "        self.text = text\n",
        "    def __str__(self):\n",
        "        return f'<p>\\n{self.text}\\n</p>'\n",
        "\n",
        "para = p(text=\"this is some body text\")\n",
        "doc_body = body(text=\"This is the body\", subelement=para)\n",
        "doc = html(subelement=doc_body)\n",
        "print(doc)\n"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "dkq-HGljY4Qm",
        "outputId": "3068b7c7-05b1-46ed-c5e7-c5eeec6b4576"
      },
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "<html>\n",
            "<body>\n",
            "This is the body\n",
            "<p>\n",
            "this is some body text\n",
            "</p>\n",
            "</body>\n",
            "</html>\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "VEzyr_5Vai-_"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}